﻿using System;
using System.IO;
using System.Collections.Generic;
using System.Xml.Serialization;
using HappyTemplate;

//To regnereate Demo.cs after changes to Demo.xsd:
//		A VS command prompt, cd to the HappyTemplateDemo project directory then run:
//		xsd Demo.xsd /c /namespace:HappyTemplateDemo
namespace HappyTemplateDemo
{


	class Program
	{
		static void HandleException(Exception e, string whileFmt, params object[] args)
		{
			if (!String.IsNullOrEmpty(whileFmt))
			{
				Console.Error.WriteLine(whileFmt, args);
			}

			Console.Error.WriteLine("Exception:  {0}\nMessage:  {1}", e.GetType(), e.Message);

			TemplateExecutionException teex = e as TemplateExecutionException;
			if(teex != null)
				Console.Error.WriteLine("Location:  {0}", teex.Location);

			if(e.InnerException != null)
				HandleException(e.InnerException, "Inner Exception:");
		}

		static TemplateObject GetTemplateObject(DatabaseTableColumn column)
		{
			TemplateObject retval = new TemplateObject(column.Name);
			retval["Name"] = column.Name;
			retval["Nullable"] = column.Nullable;
			retval["PrimaryKey"] = column.PrimaryKey;
			retval["Identity"] = column.Identity;
			retval["DataType"] = column.DataType;
			retval["Length"] = column.Length >= 0 ? column.Length.ToString() : "";
			return retval;
		}

		static TemplateObject GetTemplateObject(DatabaseTable table)
		{
			TemplateObject retval = new TemplateObject(table.Name);


			retval["Schema"] = table.Schema; 
			retval["Name"] = table.Name;

			List<TemplateObject> columns = new List<TemplateObject>();
			foreach (DatabaseTableColumn column in table.Column)
				columns.Add(GetTemplateObject(column));

			retval["Columns"] = columns;

			return retval;
		}

		static TemplateObject GetTemplateObject(Database db)
		{
			TemplateObject retval = new TemplateObject();
			List<TemplateObject> tables = new List<TemplateObject>();

			if(db.Items == null)
				throw new ApplicationException("Specified database contains no tables!");

			foreach(DatabaseTable table in db.Items)
				tables.Add(GetTemplateObject(table));

			retval["Tables"] = tables;

			return retval;
		}

		static void Main(string[] args)
		{
			TemplateSet templateSet;
			Database db;

			//Load XML file first...
			try
			{
				XmlSerializer serializer = new XmlSerializer(typeof(Database));
				FileStream stream = File.Open("Demo.xml", FileMode.Open);
				db = (Database) serializer.Deserialize(stream);
			}
			catch (Exception e)
			{
				HandleException(e, "While loading XML data:");
				return;
			}

			//Load and parse the template:
			try
			{
				SourceErrorCollection sec;
				templateSet = TemplateParser.ParseTemplateSet("Demo.hts", out sec);
				if(sec.Count > 0)
				{
					sec.PrintAll(Console.Error);
					return;
				}

				templateSet.Context["database"] = GetTemplateObject(db);
				templateSet.Context["aNullValue"] = null;
				
			}
			catch(Exception e)
			{
				HandleException(e, "While loading the template:");
				return;
			}

			//Use the template and the loaded XML to generate the output;
			try
			{
				using (FileStream outputStream = File.Open("DemoOutput.txt", FileMode.Create, FileAccess.Write))
				using (StreamWriter writer = new StreamWriter(outputStream))
				{
					templateSet.ExecuteTemplate(writer, "main");
				}
			}
			catch(TemplateExecutionException teex)
			{
				Console.Error.WriteLine(teex.ToString());
			}
			catch(Exception e)
			{
				HandleException(e, "While generating output:");
			}

		}
	}
}
